#include "tester.h"

using namespace std;
using namespace cv;

int Tester::GetRegions(cv::Mat &image, std::vector<uint> &labels)
{
	uint label = 0;
	for (int i = 0; i < image.rows; ++i)
	{
		for (int j = 0; j < image.cols; ++j)
		{
			if (labels[i * image.cols + j] == 0 && image.at<uchar>(i, j) == 255)
			{
				label++;
				PutLabel(image, labels, label, i, j);
			}
		}
	}
	return label;
}

void Tester::PutLabel(cv::Mat &image, std::vector<uint> &labels, uint label, uint i, uint j)
{
	if (labels[i * image.cols + j] == 0 && image.at<uchar>(i, j) == 255)
	{
		labels[i * image.cols + j] = label;

		if (i > 0)
			PutLabel(image, labels, label, i - 1, j);

		if (i < image.rows - 1)
			PutLabel(image, labels, label, i + 1, j);

		if (j > 0)
			PutLabel(image, labels, label, i, j - 1);

		if (j < image.cols - 1)
			PutLabel(image, labels, label, i, j + 1);
	}
}

void Tester::Compute(std::string groundThruth, std::string result, int first, int last)
{
	string ext = ".bmp";
	for (int i = first; i < last; ++i)
	{
		Mat truth = imread(groundThruth + to_string(i) + ext, CV_LOAD_IMAGE_GRAYSCALE);
		Mat heads = imread(result + to_string(i) + "e" + ext, CV_LOAD_IMAGE_GRAYSCALE);

		vector<uint> labelTr(truth.rows * truth.cols, 0);
		vector<uint> labelRes(heads.rows * heads.cols, 0);

		int objTr = GetRegions(truth, labelTr);
		int objRes = GetRegions(heads, labelRes);

		allPeople += objTr;
		allDetected += objRes;

		Compare(objTr, objRes, labelTr, labelRes, truth, heads);
	}
	cout << "allPeople: " << allPeople << endl;
	cout <<	"allDetected: " << allDetected << endl;
	cout << "correctDetected: " << correctDetected << endl;
	cout << "extraDetected: " << extraDetected << endl;
	cout << "falseDetected: " << falseDetected << endl;
	cout << endl << endl;
}

void Tester::Compare(int objTr, int objRes, std::vector<uint> lblTr, std::vector<uint> lblRes, cv::Mat imTr, cv::Mat imRes)
{
	vector<pair<int, int>> crrct_false(objRes, pair<int, int>(0,0));

	for (int i = 0; i < imRes.rows; ++i)
	{
		for (int j = 0; j < imRes.cols; ++j)
		{
			if (lblRes[i * imRes.cols + j] != 0 && lblTr[i * imTr.cols + j] != 0)
			{
				crrct_false[lblRes[i * imRes.cols + j] - 1].first++;
			}
			else if (lblRes[i * imRes.cols + j] != 0)
			{
				crrct_false[lblRes[i * imRes.cols + j] - 1].second++;
			}
		}
	}

	for (int i = 0; i < objRes; ++i)
	{
		int correct = crrct_false[i].first;
		int not_correct = crrct_false[i].second;

		if (correct == 0) 
		{ 
			extraDetected++; 
			continue; 
		}

		if (float(not_correct) / float(correct) <= 0.5)
		{
			correctDetected++;
		}
		else {
			falseDetected++;
		}
	}
}
